package cn.murky.admin.core.utils;


import cn.dev33.satoken.exception.NotLoginException;
import cn.murky.security.SecurityCache;
import cn.murky.security.entity.SecurityUserInfo;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.Solon;
import org.noear.solon.core.handle.Context;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.concurrent.Callable;

@Slf4j
public class SecurityUtils {
    static SecurityCache<SecurityUserInfo> securityCache;

    static {
        Solon.context().getBeanAsync(SecurityCache.class, systemSecurityCache ->{
            securityCache=systemSecurityCache;
        });
    }
    public static ScopedValue<SecurityUserInfo> SECURITY_USERINFO = ScopedValue.newInstance();

    /**
     * 获取当前登录用户ID
     * @return 用户id
     */
    public static Long getUserId(){
        return getUserInfo().getUserId();
    }

    /**
     * 获取当前登录用户信息
     * @return  当前登录用户信息
     */
    public static SecurityUserInfo getUserInfo() throws NotLoginException {
        return get().orElseGet(() -> securityCache.getUserInfo());
    }

    /**
     * 获取指定token的用户信息
     * @return  token的用户信息
     */
    public static SecurityUserInfo getUserInfo(String token){
        return securityCache.getUserInfo(token);
    }

    /**
     * 保存当前登录用户信息
     * @param securityUser 登录用户信息
     */
    public static void setUserInfo(SecurityUserInfo securityUser){
        securityCache.setUserInfo(securityUser);
    }

    /**
     * 修改当前登录用户信息
     */
    public static void delUserInfo(){
        securityCache.delUserInfo();
    }

    public static Boolean isAdmin() throws NotLoginException {
        return getUserInfo().getAdmin();
    }

    public static void runnable(SecurityUserInfo securityUserInfo, Runnable runnable) throws RuntimeException {
        ScopedValue.runWhere(SECURITY_USERINFO, securityUserInfo, runnable);
    }

    public static <V> V callable(SecurityUserInfo securityUserInfo, Callable<V> callable) throws Exception {
        return ScopedValue.callWhere(SECURITY_USERINFO, securityUserInfo, callable);
    }

    private static Optional<SecurityUserInfo> get(){
        try{
            return Optional.ofNullable(SECURITY_USERINFO.get());
        }catch (NoSuchElementException ex){
            log.debug(STR."[SecurityUtils.get] ---> \{Context.current().path()} 作用域中无SecurityUserInfo对象返回空");
            return Optional.empty();
        }

    }
}
